package org.flintparticles.twoD.stage3d.images
{
	import flash.display.BitmapData;
	import flash.display3D.Context3D;
	import flash.display3D.Context3DTextureFormat;
	import flash.display3D.textures.Texture;
	import flash.geom.Matrix;
	import flash.geom.Point;
	import flash.geom.Rectangle;

	public class BitmapPoll
	{
		private var _clipRect:Rectangle;
		private var _context3D:Context3D;
		private static var _texture:Texture;
		private static var _instance:BitmapPoll;
		private static var _allowInstance:Boolean;
		public function BitmapPoll(context:Context3D,singletonEnforcer:SingletonEnforcer)
		{
			if(!_allowInstance){
				throw new Error("Use Singleton.getInstance() instead of new keyword");
			}
		  _context3D=context;
		  
		
		}
		public static function getInstance(context : Context3D):BitmapPoll{
			if(_instance==null){
				_allowInstance=true;
				_instance=new BitmapPoll(context,new SingletonEnforcer());
				_allowInstance=false;
				
			}else{
				trace("The Stage3DManager already exists");
			}
			return _instance;
		}
		
		public  function fromBitmapData(data:BitmapData, generateMipMaps:Boolean=true,
											  optimizeForRenderTexture:Boolean=false):void
		{
			var origWidth:int = data.width;
			var origHeight:int = data.height;
			var legalWidth:int  = getNextPowerOfTwo(data.width);
			var legalHeight:int = getNextPowerOfTwo(data.height);
			var format:String = Context3DTextureFormat.BGRA;
			
			_texture=_context3D.createTexture(
				legalWidth, legalHeight, format, optimizeForRenderTexture);
			
			if (legalWidth > origWidth || legalHeight > origHeight)
			{
				var potData:BitmapData = new BitmapData(legalWidth, legalHeight, true, 0);
				potData.copyPixels(data, data.rect, new Point(0, 0));
				uploadTexture(potData, _texture, generateMipMaps);
				potData.dispose();
			}
			else
			{
				uploadTexture(data, _texture, generateMipMaps);
			}
			
		
		}
		private  function uploadTexture(data:BitmapData,
										texture:Texture,
										generateMipmaps:Boolean):void
		{
			texture.uploadFromBitmapData(data);
			
			if (generateMipmaps)
			{
				var currentWidth:int  = data.width  >> 1;
				var currentHeight:int = data.height >> 1;
				var level:int = 1;
				var canvas:BitmapData = new BitmapData(currentWidth, currentHeight, true, 0);
				var transform:Matrix = new Matrix(.5, 0, 0, .5);
				
				while (currentWidth >= 1 || currentHeight >= 1)
				{
					canvas.fillRect(new Rectangle(0, 0, currentWidth, currentHeight), 0);
					canvas.draw(data, transform, null, null, null, true);
					texture.uploadFromBitmapData(canvas, level++);
					transform.scale(0.5, 0.5);
					currentWidth  = currentWidth  >> 1;
					currentHeight = currentHeight >> 1;
				}
				
				canvas.dispose();
			}
		}
		
		private function getNextPowerOfTwo(number:int):int
		{
			var result:int = 1;
			while (result < number) result *= 2;
			
			return result;   
		}

		public function set context3D(value:Context3D):void
		{
			_context3D = value;
		}

		public  function get texture():Texture
		{
			return _texture;
		}


	}
}
class SingletonEnforcer{};